import { fetchEventSource } from '@microsoft/fetch-event-source'
import { getCookie } from 'cookies-next'

import { storagePrefix } from '@/shared/utils'

export interface AssistantRequestProps {
  data: any
  language: string
  onMessage: (event: any) => void
  onMessageEnd: (event: any) => void
  onOpenSuccess?: (response: any) => void
  onOpenError?: (response: any) => void
  onClose?: () => void
  onError?: (err: any) => void
}

const initAssistantRequest =
  (abortController: AbortController) =>
  ({
    data,
    language,
    onOpenSuccess,
    onOpenError,
    onMessage,
    onMessageEnd,
    onClose,
    onError,
  }: AssistantRequestProps) => {
    const accessToken = getCookie(storagePrefix('token'))
    const jsonStringfyBody = JSON.stringify({
      ...data,
      spaceHandle: true,
    })

    return fetchEventSource(
      `${process.env.NEXT_PUBLIC_API_HOST}/aigc/chat/assistant/v1/stream/instagram`,
      {
        method: 'POST',
        headers: JSON.parse(
          JSON.stringify({
            'Content-Type': 'application/json',
            Accept: 'text/event-stream,application/json',
            source: 'web',
            lang: language,
            vToken: getCookie(storagePrefix('visitorId')),
            Authorization: accessToken ? `Bearer ${accessToken}` : undefined,
          })
        ),
        body: jsonStringfyBody,
        signal: abortController.signal,
        openWhenHidden: true,

        async onopen(response) {
          try {
            if (response.ok) {
              onOpenSuccess && onOpenSuccess(response)
              return
            }
            onOpenError && onOpenError(response)
          } catch (error: any) {
            onOpenError && onOpenError(response)
            throw new Error(error)
          }
        },
        onmessage(event) {
          if (event.data == '--@DONE@--') {
            onMessageEnd(event)
          } else {
            onMessage(event)
          }
        },
        onclose() {
          abortController.abort()
          onClose && onClose()
        },
        onerror(err) {
          onError && onError(err)
          throw err
        },
      }
    )
  }

const init = () => {
  const abortController = new AbortController()
  const assistantRequest = initAssistantRequest(abortController)

  return {
    abortController,
    assistantRequest,
  }
}

export default init
